package com.exposit.zbs.service.impl;

import com.exposit.zbs.dao.*;
import com.exposit.zbs.entity.*;
import com.exposit.zbs.model.*;
import com.exposit.zbs.service.IGrantApplicationService;
import com.exposit.zbs.utils.MapperProvider;
import org.dozer.DozerBeanMapperSingletonWrapper;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;


@Service
@Transactional
public class GrantApplicationService implements IGrantApplicationService {

	@Autowired
	private IGrantAreaDAO grantAreaDAO;

	@Autowired
	private IGrantApplicationDAO grantApplicationDAO;

	@Autowired
	private ILikeDAO likeDAO;

	@Autowired
	private ICommentDAO commentDAO;

	@Autowired
	private IGrantAreaMoneyDAO grantAreaMoneyDAO;

	@Autowired
	private IMoneyTransferFromFundDAO moneyTransferFromFundDAO;

	@Autowired
	private IChangelogDAO changelogDAO;

	@Override
	public List<GrantApplication> getAllGrants() {

		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		List<GrantApplicationEntity> grantAppEntities = grantApplicationDAO.findAll();
		List<GrantApplication> grantApps = new ArrayList<GrantApplication>();
		GrantApplication t = new GrantApplication();
		for (GrantApplicationEntity currentEntity : grantAppEntities) {
			t = new GrantApplication();
			mapper.map(currentEntity, t);
			if (t != null) {
				grantApps.add(t);
			}
		}
		return grantApps;
	}

	@Override
	public List<GrantApplication> getGrantsByArea(GrantArea area, Integer count) {


		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		GrantAreaEntity grantAreaEntity = new GrantAreaEntity();
		mapper.map(area, grantAreaEntity);
		List<GrantApplicationEntity> grantAppEntities = grantApplicationDAO.listGrantApplicationByArea(grantAreaEntity);
		List<GrantApplication> grantApps = new ArrayList<GrantApplication>();
		GrantApplication t = null;
		for (GrantApplicationEntity grantAppEntity : grantAppEntities) {
			t = new GrantApplication();
			mapper.map(grantAppEntity, t);
			grantApps.add(t);
		}
		return grantApps;

	}

	@Override
	public GrantApplication getGrantById(Long id) {

		GrantApplicationEntity entity = grantApplicationDAO.findById(id);
		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		GrantApplication grantApplication = new GrantApplication();
		mapper.map(entity, grantApplication);
		return grantApplication;
	}

	@Override
	public void saveGrant(GrantApplication grant) {

		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		GrantApplicationEntity grantEntity = new GrantApplicationEntity();
		mapper.map(grant, grantEntity);
		if (grantEntity != null) {
			GrantApplicationStatusEntity status = new GrantApplicationStatusEntity();
			status.setGrantStatusId(new Long(1));
			status.setGrantStatusName("REQUESTED");
			grantEntity.setGrantApplicationStatus(status);
			Long id = grantApplicationDAO.save(grantEntity);
		}

	}

	@Override
	public boolean updateGrant(GrantApplication newGrant) {

		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		GrantApplicationEntity grantEntity = new GrantApplicationEntity();
		mapper.map(newGrant, grantEntity);
		grantApplicationDAO.update(grantEntity);
		return true;
	}

	@Override
	public void removeGrant(Long id) {

		grantApplicationDAO.delete(id);
	}

	@Override
	public GrantArea getGrantAreaById(Long id) {

		GrantAreaEntity grantAreaEntity = grantAreaDAO.findById(id);
		if (grantAreaEntity != null) {
			Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
			GrantArea grantArea = new GrantArea();
			mapper.map(grantAreaEntity, grantArea);
			return grantArea;
		} else {
			return null;
		}
	}

	@Override
	public GrantArea getGrantAreaByLink(String link) {

		GrantAreaEntity grantAreaEntity = grantAreaDAO.getGrantAreaByLink(link);
		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		GrantArea result = new GrantArea();
		mapper.map(grantAreaEntity, result);
		return result;
	}

	@Override
	public List<GrantArea> getAllAreas() {

		List<GrantAreaEntity> grantAreaEntities = grantAreaDAO.findAll();
		if (grantAreaEntities != null) {
			List<GrantArea> grantAreas = new ArrayList<GrantArea>();
			GrantArea t = null;
			for (GrantAreaEntity grantAreaEntity : grantAreaEntities) {
				t = new GrantArea();
				MapperProvider.getDozerMapper().map(grantAreaEntity, t);
				if (t != null) {
					grantAreas.add(t);
				}
			}

			return grantAreas;
		}
		return null;
	}

	@Override
	public void saveGrantArea(GrantArea area) {

		if (area != null) {
			Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
			GrantAreaEntity entity = new GrantAreaEntity();
			mapper.map(area, entity);
			grantAreaDAO.save(entity);

		}
	}

	@Override
	public void removeGrantAreaById(Long id) {

		grantAreaDAO.delete(id);
	}

	@Override
	public void saveLike(Like like) {

		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		LikeEntity likeEntity = new LikeEntity();
		mapper.map(like, likeEntity);
		likeDAO.save(likeEntity);
	}

	@Override
	public void removeLike(Like like) {

		LikeEntity likeEntity = new LikeEntity();
		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		mapper.map(like, likeEntity);
		likeDAO.delete(likeEntity);
	}

	@Override
	public Long saveComment(Comment comment) {

		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		CommentEntity entity = new CommentEntity();
		mapper.map(comment, entity);
		return commentDAO.save(entity);
	}

	public void deleteComment(Comment comment) {

		CommentEntity commentEntity = new CommentEntity();
		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		mapper.map(comment, commentEntity);
		commentDAO.delete(commentEntity.getCommentId());
	}

	@Override
	public Long saveAreaMoneyTransfer(GrantAreaMoney grantAreaMoney) {

		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		GrantAreaMoneyEntity entity = new GrantAreaMoneyEntity();
		mapper.map(grantAreaMoney, entity);
		return grantAreaMoneyDAO.save(entity);
	}

	@Override
	public List<GrantApplication> getApplicationsForAdminReview() {

		List<GrantApplicationEntity> grantAppEntities = grantApplicationDAO.getEntitiesByStatus("REQUESTED");
		List<GrantApplication> grantApps = new ArrayList<GrantApplication>();
		GrantApplication t = null;
		for (GrantApplicationEntity grantAppEntity : grantAppEntities) {
			t = new GrantApplication();
			MapperProvider.getDozerMapper().map(grantAppEntity, t);
			grantApps.add(t);
		}
		return grantApps;

	}



	@Override
	public Long getCountOfRequstedGrantApplications() {

		return grantApplicationDAO.getCountOfGrantRequests();
	}

	@Override
	public Comment getCommentById(Long id) {

		CommentEntity entity = commentDAO.findById(id);
		Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
		Comment comment = new Comment();
		mapper.map(entity, comment);
		return comment;
	}

	@Override
	public BigDecimal getAvailMoneyForArea(Long grantAreaId) {

		return grantAreaDAO.getAvailMoney(grantAreaId);
	}

	@Override
	public void saveMoneyTransferFromFund(MoneyTransferFromFund mtff) {

		MoneyTransferFromFundEntity mtffe = new MoneyTransferFromFundEntity();
		MapperProvider.getDozerMapper().map(mtff, mtffe);
		moneyTransferFromFundDAO.save(mtffe);
	}

	@Override
	public void saveChangeLogRecord(GrantChangelog clRecord) {

		GrantChangelogEntity clEntity = new GrantChangelogEntity();
		MapperProvider.getDozerMapper().map(clRecord, clEntity);
		changelogDAO.save(clEntity);
	}

	@Override
	public List<GrantChangelog> getUsersFeed(User currentUser) {

		List<GrantChangelogEntity> cleList = changelogDAO.getUsersFeed(currentUser.getUserId());
		List<GrantChangelog> logs = new ArrayList<GrantChangelog>();
		GrantChangelog t = null;
		for (GrantChangelogEntity cle : cleList) {
			t = new GrantChangelog();
			MapperProvider.getDozerMapper().map(cle, t);
			logs.add(t);
		}
		return logs;
	}

	@Override
	public User getUserByGrant(GrantApplication grant) {

		User user = (User) grant.getUser();
		return user;
	}

	@Override
	public int getAllMoney(Long grantAreaId) {

		GrantArea area = getGrantAreaById(grantAreaId);
		List<GrantApplication> grants = getGrantsByArea(area, 10);

		int result = 0;
		if (grants.size() != 0) {
			List<GrantAreaMoney> grantAreaMoney = area.getGrantAreaMoneyEntities();
			BigDecimal bd = getAvailMoneyForArea(grantAreaId);
			result += bd.intValue();
			for (GrantApplication grantApp : grants) {
				result += grantApp.getMoneyAmount();
			}
		}
		return result;
	}

	@Override
	public List<DateValueGraphicEntry> getMoneyReporyGraphic() {

		List<DateValueGraphicEntryEntity> entities = grantApplicationDAO.getMoneyToGrantsGraphicData();
		List<DateValueGraphicEntry> result = new ArrayList<DateValueGraphicEntry>();
		DateValueGraphicEntry t = null;
		for (DateValueGraphicEntryEntity d : entities) {
			t = new DateValueGraphicEntry();
			MapperProvider.getDozerMapper().map(d, t);
			result.add(t);
		}
		return result;
	}

	@Override
	public List<GrantApplication> getFinishedGrantApplications() {

		List<GrantApplicationEntity> grantAppEntities = grantApplicationDAO.getEntitiesByStatus("ENDED");
		List<GrantApplication> grantApps = new ArrayList<GrantApplication>();
		GrantApplication t = null;
		for (GrantApplicationEntity grantAppEntity : grantAppEntities) {
			t = new GrantApplication();
			MapperProvider.getDozerMapper().map(grantAppEntity, t);
			grantApps.add(t);
		}
		return grantApps;
	}
}


